﻿/* ================================================================================
<copyright file="InMemoryLogger.cs" company="The Framework Factory, LLC" lastWriteTime="12/05/2012 23:23:47 PM">
  Copyright (c) 2012 The Framework Factory, LLC.  All rights reserved.
</copyright>
=================================================================================== */
using System;
using System.Collections.Generic;
using System.Text;

using log4net.Core;
using log4net.Util;

namespace FWF.Logging.Test
{
    /// <summary>
    /// 
    /// </summary>
    public class InMemoryLogger : IFWFLog
    {
        private readonly IDictionary<Level, List<string>> _logs = new Dictionary<Level, List<string>>();

        /// <summary>
        /// Initializes a new instance of the <see cref="InMemoryLogger"/> class.
        /// </summary>
        public InMemoryLogger()
        {
            Reset();
        }

        #region IFWFLog Members

        /// <summary>
        /// Checks if this logger is enabled for the Notice level.
        /// </summary>
        /// <value>
        /// <c>true</c> if this logger is enabled for Notice events, <c>false</c> otherwise.
        /// </value>
        /// <seealso cref="Notice(object)" />
        /// <remarks>
        ///   <para>
        /// This function is intended to lessen the computational cost of
        /// disabled log Notice statements.
        ///   </para>
        ///   <para> For some ILog interface <c>log</c>, when you write:</para>
        ///   <code lang="C#">
        /// log.Notice("This is entry number: " + i );
        ///   </code>
        ///   <para>
        /// You incur the cost constructing the message, string construction and concatenation in
        /// this case, regardless of whether the message is logged or not.
        ///   </para>
        ///   <para>
        /// If you are worried about speed (who isn't), then you should write:
        ///   </para>
        ///   <code lang="C#">
        /// if (log.IsNoticeEnabled)
        /// {
        /// log.Notice("This is entry number: " + i );
        /// }
        ///   </code>
        ///   <para>
        /// This way you will not incur the cost of parameter
        /// construction if debugging is disabled for <c>log</c>. On
        /// the other hand, if the <c>log</c> is Notice enabled, you
        /// will incur the cost of evaluating whether the logger is Notice
        /// enabled twice. Once in <see cref="IsNoticeEnabled" /> and once in
        /// the <see cref="Notice(object)" />.  This is an insignificant overhead
        /// since evaluating a logger takes about 1% of the time it
        /// takes to actually log. This is the preferred style of logging.
        ///   </para>
        ///   <para>Alternatively if your logger is available statically then the is Notice
        /// enabled state can be stored in a static variable like this:
        ///   </para>
        ///   <code lang="C#">
        /// private static readonly bool isNoticeEnabled = log.IsNoticeEnabled;
        ///   </code>
        ///   <para>
        /// Then when you come to log you can write:
        ///   </para>
        ///   <code lang="C#">
        /// if (isNoticeEnabled)
        /// {
        /// log.Notice("This is entry number: " + i );
        /// }
        ///   </code>
        ///   <para>
        /// This way the Notice enabled state is only queried once
        /// when the class is loaded. Using a <c>private static readonly</c>
        /// variable is the most efficient because it is a run time constant
        /// and can be heavily optimized by the JIT compiler.
        ///   </para>
        ///   <para>
        /// Of course if you use a static readonly variable to
        /// hold the enabled state of the logger then you cannot
        /// change the enabled state at runtime to vary the logging
        /// that is produced. You have to decide if you need absolute
        /// speed or runtime flexibility.
        ///   </para>
        /// </remarks>
        public bool IsNoticeEnabled
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Checks if this logger is enabled for the Trace level.
        /// </summary>
        /// <value>
        /// <c>true</c> if this logger is enabled for Trace events, <c>false</c> otherwise.
        /// </value>
        /// <seealso cref="Trace(object)" />
        /// <remarks>
        ///   <para>
        /// This function is intended to lessen the computational cost of
        /// disabled log Trace statements.
        ///   </para>
        ///   <para> For some ILog interface <c>log</c>, when you write:</para>
        ///   <code lang="C#">
        /// log.Trace("This is entry number: " + i );
        ///   </code>
        ///   <para>
        /// You incur the cost constructing the message, string construction and concatenation in
        /// this case, regardless of whether the message is logged or not.
        ///   </para>
        ///   <para>
        /// If you are worried about speed (who isn't), then you should write:
        ///   </para>
        ///   <code lang="C#">
        /// if (log.IsTraceEnabled)
        /// {
        /// log.Trace("This is entry number: " + i );
        /// }
        ///   </code>
        ///   <para>
        /// This way you will not incur the cost of parameter
        /// construction if debugging is disabled for <c>log</c>. On
        /// the other hand, if the <c>log</c> is Trace enabled, you
        /// will incur the cost of evaluating whether the logger is Trace
        /// enabled twice. Once in <see cref="IsTraceEnabled" /> and once in
        /// the <see cref="Trace(object)" />.  This is an insignificant overhead
        /// since evaluating a logger takes about 1% of the time it
        /// takes to actually log. This is the preferred style of logging.
        ///   </para>
        ///   <para>Alternatively if your logger is available statically then the is Trace
        /// enabled state can be stored in a static variable like this:
        ///   </para>
        ///   <code lang="C#">
        /// private static readonly bool isTraceEnabled = log.IsTraceEnabled;
        ///   </code>
        ///   <para>
        /// Then when you come to log you can write:
        ///   </para>
        ///   <code lang="C#">
        /// if (isTraceEnabled)
        /// {
        /// log.Trace("This is entry number: " + i );
        /// }
        ///   </code>
        ///   <para>
        /// This way the Trace enabled state is only queried once
        /// when the class is loaded. Using a <c>private static readonly</c>
        /// variable is the most efficient because it is a run time constant
        /// and can be heavily optimized by the JIT compiler.
        ///   </para>
        ///   <para>
        /// Of course if you use a static readonly variable to
        /// hold the enabled state of the logger then you cannot
        /// change the enabled state at runtime to vary the logging
        /// that is produced. You have to decide if you need absolute
        /// speed or runtime flexibility.
        ///   </para>
        /// </remarks>
        public bool IsTraceEnabled
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Checks if this logger is enabled for the Verbose level.
        /// </summary>
        /// <value>
        /// <c>true</c> if this logger is enabled for Verbose events, <c>false</c> otherwise.
        /// </value>
        /// <seealso cref="Verbose(object)" />
        /// <remarks>
        ///   <para>
        /// This function is intended to lessen the computational cost of
        /// disabled log Verbose statements.
        ///   </para>
        ///   <para> For some ILog interface <c>log</c>, when you write:</para>
        ///   <code lang="C#">
        /// log.Verbose("This is entry number: " + i );
        ///   </code>
        ///   <para>
        /// You incur the cost constructing the message, string construction and concatenation in
        /// this case, regardless of whether the message is logged or not.
        ///   </para>
        ///   <para>
        /// If you are worried about speed (who isn't), then you should write:
        ///   </para>
        ///   <code lang="C#">
        /// if (log.IsVerboseEnabled)
        /// {
        /// log.Verbose("This is entry number: " + i );
        /// }
        ///   </code>
        ///   <para>
        /// This way you will not incur the cost of parameter
        /// construction if debugging is disabled for <c>log</c>. On
        /// the other hand, if the <c>log</c> is Verbose enabled, you
        /// will incur the cost of evaluating whether the logger is Verbose
        /// enabled twice. Once in <see cref="IsVerboseEnabled" /> and once in
        /// the <see cref="Verbose(object)" />.  This is an insignificant overhead
        /// since evaluating a logger takes about 1% of the time it
        /// takes to actually log. This is the preferred style of logging.
        ///   </para>
        ///   <para>Alternatively if your logger is available statically then the is Verbose
        /// enabled state can be stored in a static variable like this:
        ///   </para>
        ///   <code lang="C#">
        /// private static readonly bool isVerboseEnabled = log.IsVerboseEnabled;
        ///   </code>
        ///   <para>
        /// Then when you come to log you can write:
        ///   </para>
        ///   <code lang="C#">
        /// if (isVerboseEnabled)
        /// {
        /// log.Verbose("This is entry number: " + i );
        /// }
        ///   </code>
        ///   <para>
        /// This way the Verbose enabled state is only queried once
        /// when the class is loaded. Using a <c>private static readonly</c>
        /// variable is the most efficient because it is a run time constant
        /// and can be heavily optimized by the JIT compiler.
        ///   </para>
        ///   <para>
        /// Of course if you use a static readonly variable to
        /// hold the enabled state of the logger then you cannot
        /// change the enabled state at runtime to vary the logging
        /// that is produced. You have to decide if you need absolute
        /// speed or runtime flexibility.
        ///   </para>
        /// </remarks>
        public bool IsVerboseEnabled
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Checks if this logger is enabled for the Severe level.
        /// </summary>
        /// <value>
        /// <c>true</c> if this logger is enabled for Severe events, <c>false</c> otherwise.
        /// </value>
        /// <seealso cref="Severe(object)" />
        /// <remarks>
        ///   <para>
        /// This function is intended to lessen the computational cost of
        /// disabled log Severe statements.
        ///   </para>
        ///   <para> For some ILog interface <c>log</c>, when you write:</para>
        ///   <code lang="C#">
        /// log.Severe("This is entry number: " + i );
        ///   </code>
        ///   <para>
        /// You incur the cost constructing the message, string construction and concatenation in
        /// this case, regardless of whether the message is logged or not.
        ///   </para>
        ///   <para>
        /// If you are worried about speed (who isn't), then you should write:
        ///   </para>
        ///   <code lang="C#">
        /// if (log.IsSevereEnabled)
        /// {
        /// log.Severe("This is entry number: " + i );
        /// }
        ///   </code>
        ///   <para>
        /// This way you will not incur the cost of parameter
        /// construction if debugging is disabled for <c>log</c>. On
        /// the other hand, if the <c>log</c> is Severe enabled, you
        /// will incur the cost of evaluating whether the logger is Severe
        /// enabled twice. Once in <see cref="IsSevereEnabled" /> and once in
        /// the <see cref="Severe(object)" />.  This is an insignificant overhead
        /// since evaluating a logger takes about 1% of the time it
        /// takes to actually log. This is the preferred style of logging.
        ///   </para>
        ///   <para>Alternatively if your logger is available statically then the is Severe
        /// enabled state can be stored in a static variable like this:
        ///   </para>
        ///   <code lang="C#">
        /// private static readonly bool isSevereEnabled = log.IsSevereEnabled;
        ///   </code>
        ///   <para>
        /// Then when you come to log you can write:
        ///   </para>
        ///   <code lang="C#">
        /// if (isSevereEnabled)
        /// {
        /// log.Severe("This is entry number: " + i );
        /// }
        ///   </code>
        ///   <para>
        /// This way the Severe enabled state is only queried once
        /// when the class is loaded. Using a <c>private static readonly</c>
        /// variable is the most efficient because it is a run time constant
        /// and can be heavily optimized by the JIT compiler.
        ///   </para>
        ///   <para>
        /// Of course if you use a static readonly variable to
        /// hold the enabled state of the logger then you cannot
        /// change the enabled state at runtime to vary the logging
        /// that is produced. You have to decide if you need absolute
        /// speed or runtime flexibility.
        ///   </para>
        /// </remarks>
        public bool IsSevereEnabled
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is statistics enabled.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is statistics enabled; otherwise, <c>false</c>.
        /// </value>
        public bool IsStatisticsEnabled
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Logs the specified logging event.
        /// </summary>
        /// <param name="loggingEvent">The logging event.</param>
        public void Log( LoggingEventData loggingEvent )
        {
            _logs[ loggingEvent.Level ].Add( loggingEvent.Message );
        }

        /// <summary>
        /// Create a LoggingEvent component based upon the current context of the call.
        /// </summary>
        /// <param name="declaringType"></param>
        /// <returns></returns>
        public LoggingEventData PrepareLogEvent( Type declaringType )
        {
            var logData = new LoggingEventData();
            logData.Properties = new PropertiesDictionary();
            return logData;
        }

        /// <summary>
        /// Log a message object with the Notice level.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <overloads>Log a message object with the Notice level.</overloads>
        ///   <seealso cref="Notice(object,Exception)" />
        ///   <seealso cref="IsNoticeEnabled" />
        /// <remarks>
        ///   <para>
        /// This method first checks if this logger is <c>Notice</c>
        /// enabled by comparing the level of this logger with the
        /// Notice level. If this logger is
        ///   <c>Notice</c> enabled, then it converts the message object
        /// (passed as parameter) to a string by invoking the appropriate
        ///   <see cref="log4net.ObjectRenderer.IObjectRenderer" />. It then
        /// proceeds to call all the registered appenders in this logger
        /// and also higher in the hierarchy depending on the value of
        /// the additivity flag.
        ///   </para>
        ///   <para><b>WARNING</b> Note that passing an <see cref="Exception" />
        /// to this method will print the name of the <see cref="Exception" />
        /// but no stack trace. To print a stack trace use the
        ///   <see cref="Notice(object,Exception)" /> form instead.
        ///   </para>
        /// </remarks>
        public void Notice( object message )
        {
            _logs[ Level.Notice ].Add( message as string );
        }

        /// <summary>
        /// Log a message object with the Notice level including
        /// the stack trace of the <see cref="Exception" /> passed
        /// as a parameter.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <param name="exception">The exception to log, including its stack trace.</param>
        /// <seealso cref="Notice(object)" />
        ///   <seealso cref="IsNoticeEnabled" />
        /// <remarks>
        /// See the <see cref="Notice(object)" /> form for more detailed information.
        /// </remarks>
        public void Notice( object message, Exception exception )
        {
            var builder = new StringBuilder();
            builder.AppendLine( message as string );
            builder.AppendLine( ExceptionLib.FormatException( exception ) );

            _logs[ Level.Notice ].Add( builder.ToString() );
        }

        /// <summary>
        /// Logs a formatted message string with the Notice level.
        /// </summary>
        /// <param name="format">A String containing zero or more format items</param>
        /// <param name="args">An Object array containing zero or more objects to format</param>
        /// <overloads>Log a formatted string with the Notice level.</overloads>
        ///   <seealso cref="Notice(object)" />
        ///   <seealso cref="IsNoticeEnabled" />
        /// <remarks>
        ///   <para>
        /// The message is formatted using the <c>String.Format</c> method. See
        ///   <see cref="String.Format(string, object[])" /> for details of the syntax of the format string and the behavior
        /// of the formatting.
        ///   </para>
        ///   <para>
        /// This method does not take an <see cref="Exception" /> object to include in the
        /// log event. To pass an <see cref="Exception" /> use one of the <see cref="Notice(object,Exception)" />
        /// methods instead.
        ///   </para>
        /// </remarks>
        public void NoticeFormat( string format, params object[] args )
        {
            _logs[ Level.Notice ].Add( string.Format( format, args ) );
        }

        /// <summary>
        /// Log a message object with the Trace level.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <overloads>Log a message object with the Trace level.</overloads>
        ///   <seealso cref="Trace(object,Exception)" />
        ///   <seealso cref="IsTraceEnabled" />
        /// <remarks>
        ///   <para>
        /// This method first checks if this logger is <c>Trace</c>
        /// enabled by comparing the level of this logger with the
        /// Trace level. If this logger is
        ///   <c>Trace</c> enabled, then it converts the message object
        /// (passed as parameter) to a string by invoking the appropriate
        ///   <see cref="log4net.ObjectRenderer.IObjectRenderer" />. It then
        /// proceeds to call all the registered appenders in this logger
        /// and also higher in the hierarchy depending on the value of
        /// the additivity flag.
        ///   </para>
        ///   <para><b>WARNING</b> Note that passing an <see cref="Exception" />
        /// to this method will print the name of the <see cref="Exception" />
        /// but no stack trace. To print a stack trace use the
        ///   <see cref="Trace(object,Exception)" /> form instead.
        ///   </para>
        /// </remarks>
        public void Trace( object message )
        {
            _logs[ Level.Trace ].Add( message as string );
        }

        /// <summary>
        /// Log a message object with the Trace level including
        /// the stack trace of the <see cref="Exception" /> passed
        /// as a parameter.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <param name="exception">The exception to log, including its stack trace.</param>
        /// <seealso cref="Trace(object)" />
        ///   <seealso cref="IsTraceEnabled" />
        /// <remarks>
        /// See the <see cref="Trace(object)" /> form for more detailed information.
        /// </remarks>
        public void Trace( object message, Exception exception )
        {
            var builder = new StringBuilder();
            builder.AppendLine( message as string );
            builder.AppendLine( ExceptionLib.FormatException( exception ) );

            _logs[ Level.Trace ].Add( builder.ToString() );
        }

        /// <summary>
        /// Logs a formatted message string with the Trace level.
        /// </summary>
        /// <param name="format">A String containing zero or more format items</param>
        /// <param name="args">An Object array containing zero or more objects to format</param>
        /// <overloads>Log a formatted string with the Trace level.</overloads>
        ///   <seealso cref="Trace(object)" />
        ///   <seealso cref="IsTraceEnabled" />
        /// <remarks>
        ///   <para>
        /// The message is formatted using the <c>String.Format</c> method. See
        ///   <see cref="String.Format(string, object[])" /> for details of the syntax of the format string and the behavior
        /// of the formatting.
        ///   </para>
        ///   <para>
        /// This method does not take an <see cref="Exception" /> object to include in the
        /// log event. To pass an <see cref="Exception" /> use one of the <see cref="Trace(object,Exception)" />
        /// methods instead.
        ///   </para>
        /// </remarks>
        public void TraceFormat( string format, params object[] args )
        {
            _logs[ Level.Trace ].Add( string.Format( format, args ) );
        }

        /// <summary>
        /// Log a message object with the Verbose level.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <overloads>Log a message object with the Verbose level.</overloads>
        ///   <seealso cref="Verbose(object,Exception)" />
        ///   <seealso cref="IsVerboseEnabled" />
        /// <remarks>
        ///   <para>
        /// This method first checks if this logger is <c>Verbose</c>
        /// enabled by comparing the level of this logger with the
        /// Verbose level. If this logger is
        ///   <c>Verbose</c> enabled, then it converts the message object
        /// (passed as parameter) to a string by invoking the appropriate
        ///   <see cref="log4net.ObjectRenderer.IObjectRenderer" />. It then
        /// proceeds to call all the registered appenders in this logger
        /// and also higher in the hierarchy depending on the value of
        /// the additivity flag.
        ///   </para>
        ///   <para><b>WARNING</b> Note that passing an <see cref="Exception" />
        /// to this method will print the name of the <see cref="Exception" />
        /// but no stack Verbose. To print a stack Verbose use the
        ///   <see cref="Verbose(object,Exception)" /> form instead.
        ///   </para>
        /// </remarks>
        public void Verbose( object message )
        {
            _logs[ Level.Verbose ].Add( message as string );
        }

        /// <summary>
        /// Log a message object with the Verbose level including
        /// the stack Verbose of the <see cref="Exception" /> passed
        /// as a parameter.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <param name="exception">The exception to log, including its stack Verbose.</param>
        /// <seealso cref="Verbose(object)" />
        ///   <seealso cref="IsVerboseEnabled" />
        /// <remarks>
        /// See the <see cref="Verbose(object)" /> form for more detailed information.
        /// </remarks>
        public void Verbose( object message, Exception exception )
        {
            var builder = new StringBuilder();
            builder.AppendLine( message as string );
            builder.AppendLine( ExceptionLib.FormatException( exception ) );

            _logs[ Level.Verbose ].Add( builder.ToString() );
        }

        /// <summary>
        /// Logs a formatted message string with the Verbose level.
        /// </summary>
        /// <param name="format">A String containing zero or more format items</param>
        /// <param name="args">An Object array containing zero or more objects to format</param>
        /// <overloads>Log a formatted string with the Verbose level.</overloads>
        ///   <seealso cref="Verbose(object)" />
        ///   <seealso cref="IsVerboseEnabled" />
        /// <remarks>
        ///   <para>
        /// The message is formatted using the <c>String.Format</c> method. See
        ///   <see cref="String.Format(string, object[])" /> for details of the syntax of the format string and the behavior
        /// of the formatting.
        ///   </para>
        ///   <para>
        /// This method does not take an <see cref="Exception" /> object to include in the
        /// log event. To pass an <see cref="Exception" /> use one of the <see cref="Verbose(object,Exception)" />
        /// methods instead.
        ///   </para>
        /// </remarks>
        public void VerboseFormat( string format, params object[] args )
        {
            _logs[ Level.Verbose ].Add( string.Format( format, args ) );
        }

        /// <summary>
        /// Log a message object with the Severe level.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <overloads>Log a message object with the Severe level.</overloads>
        ///   <seealso cref="Severe(object,Exception)" />
        ///   <seealso cref="IsSevereEnabled" />
        /// <remarks>
        ///   <para>
        /// This method first checks if this logger is <c>Severe</c>
        /// enabled by comparing the level of this logger with the
        /// Severe level. If this logger is
        ///   <c>Severe</c> enabled, then it converts the message object
        /// (passed as parameter) to a string by invoking the appropriate
        ///   <see cref="log4net.ObjectRenderer.IObjectRenderer" />. It then
        /// proceeds to call all the registered appenders in this logger
        /// and also higher in the hierarchy depending on the value of
        /// the additivity flag.
        ///   </para>
        ///   <para><b>WARNING</b> Note that passing an <see cref="Exception" />
        /// to this method will print the name of the <see cref="Exception" />
        /// but no stack Severe. To print a stack Severe use the
        ///   <see cref="Severe(object,Exception)" /> form instead.
        ///   </para>
        /// </remarks>
        public void Severe( object message )
        {
            _logs[ Level.Severe ].Add( message as string );
        }

        /// <summary>
        /// Log a message object with the Severe level including
        /// the stack Severe of the <see cref="Exception" /> passed
        /// as a parameter.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <param name="exception">The exception to log, including its stack Severe.</param>
        /// <seealso cref="Severe(object)" />
        ///   <seealso cref="IsSevereEnabled" />
        /// <remarks>
        /// See the <see cref="Severe(object)" /> form for more detailed information.
        /// </remarks>
        public void Severe( object message, Exception exception )
        {
            var builder = new StringBuilder();
            builder.AppendLine( message as string );
            builder.AppendLine( ExceptionLib.FormatException( exception ) );

            _logs[ Level.Severe ].Add( builder.ToString() );
        }

        /// <summary>
        /// Logs a formatted message string with the Severe level.
        /// </summary>
        /// <param name="format">A String containing zero or more format items</param>
        /// <param name="args">An Object array containing zero or more objects to format</param>
        /// <overloads>Log a formatted string with the Severe level.</overloads>
        ///   <seealso cref="Severe(object)" />
        ///   <seealso cref="IsSevereEnabled" />
        /// <remarks>
        ///   <para>
        /// The message is formatted using the <c>String.Format</c> method. See
        ///   <see cref="String.Format(string, object[])" /> for details of the syntax of the format string and the behavior
        /// of the formatting.
        ///   </para>
        ///   <para>
        /// This method does not take an <see cref="Exception" /> object to include in the
        /// log event. To pass an <see cref="Exception" /> use one of the <see cref="Severe(object,Exception)" />
        /// methods instead.
        ///   </para>
        /// </remarks>
        public void SevereFormat( string format, params object[] args )
        {
            _logs[ Level.Verbose ].Add( string.Format( format, args ) );
        }

        /// <summary>
        /// Log a message object with the Statistic level.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <seealso cref="Statistic(object)" />
        ///   <seealso cref="IsStatisticsEnabled" />
        /// <remarks>
        /// See the <see cref="Statistic(object)" /> form for more detailed information.
        /// </remarks>
        public void Statistic(object message)
        {
            _logs[ExtendedLogImplementation.Statistics].Add(message as string);
        }

        /// <summary>
        /// Statistics the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="exception">The exception.</param>
        public void Statistic( object message, Exception exception )
        {
            var builder = new StringBuilder();
            builder.AppendLine(message as string);
            builder.AppendLine(ExceptionLib.FormatException(exception));

            _logs[ExtendedLogImplementation.Statistics].Add(builder.ToString());
        }

        /// <summary>
        /// Logs a formatted message string with the Statistic level.
        /// </summary>
        /// <param name="format">A String containing zero or more format items</param>
        /// <param name="args">An Object array containing zero or more objects to format</param>
        /// <seealso cref="Statistic(object)" />
        ///   <seealso cref="IsStatisticsEnabled" />
        /// <remarks>
        /// The message is formatted using the <c>String.Format</c> method. See
        /// <see cref="String.Format(string, object[])" /> for details of the syntax of the format string and the behavior
        /// of the formatting.
        /// </remarks>
        public void StatisticFormat( string format, params object[] args )
        {
            _logs[ExtendedLogImplementation.Statistics].Add(string.Format(format, args));
        }

        /// <summary>
        /// </summary>
        /// <param name="ifTrue">if set to <c>true</c> [if true].</param>
        /// <param name="message">The message.</param>
        public void WarnIf( bool ifTrue, string message )
        {
            if ( ifTrue )
            {
                _logs[ Level.Warn ].Add( message );
            }
        }

        #endregion

        #region ILog Members

        /// <summary>
        /// Debugs the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="exception">The exception.</param>
        public void Debug( object message, Exception exception )
        {
            var builder = new StringBuilder();
            builder.AppendLine( message as string );
            builder.AppendLine( ExceptionLib.FormatException( exception ) );

            _logs[ Level.Debug ].Add( builder.ToString() );
        }

        /// <summary>
        /// Debugs the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Debug( object message )
        {
            _logs[ Level.Debug ].Add( message as string );
        }

        /// <summary>
        /// Debugs the format.
        /// </summary>
        /// <param name="provider">The provider.</param>
        /// <param name="format">The format.</param>
        /// <param name="args">The args.</param>
        public void DebugFormat( IFormatProvider provider, string format, params object[] args )
        {
            _logs[ Level.Debug ].Add( string.Format( format, args ) );
        }

        /// <summary>
        /// Debugs the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        /// <param name="arg1">The arg1.</param>
        /// <param name="arg2">The arg2.</param>
        public void DebugFormat( string format, object arg0, object arg1, object arg2 )
        {
            _logs[ Level.Debug ].Add( string.Format( format, arg0, arg1, arg2 ) );
        }

        /// <summary>
        /// Debugs the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        /// <param name="arg1">The arg1.</param>
        public void DebugFormat( string format, object arg0, object arg1 )
        {
            _logs[ Level.Debug ].Add( string.Format( format, arg0, arg1 ) );
        }

        /// <summary>
        /// Debugs the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        public void DebugFormat( string format, object arg0 )
        {
            _logs[ Level.Debug ].Add( string.Format( format, arg0 ) );
        }

        /// <summary>
        /// Debugs the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="args">The args.</param>
        public void DebugFormat( string format, params object[] args )
        {
            _logs[ Level.Debug ].Add( string.Format( format, args ) );
        }

        /// <summary>
        /// Errors the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="exception">The exception.</param>
        public void Error( object message, Exception exception )
        {
            var builder = new StringBuilder();
            builder.AppendLine( message as string );
            builder.AppendLine( ExceptionLib.FormatException( exception ) );

            _logs[ Level.Error ].Add( builder.ToString() );
        }

        /// <summary>
        /// Errors the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Error( object message )
        {
            _logs[ Level.Error ].Add( message as string );
        }

        /// <summary>
        /// Errors the format.
        /// </summary>
        /// <param name="provider">The provider.</param>
        /// <param name="format">The format.</param>
        /// <param name="args">The args.</param>
        public void ErrorFormat( IFormatProvider provider, string format, params object[] args )
        {
            _logs[ Level.Error ].Add( string.Format( format, args ) );
        }

        /// <summary>
        /// Errors the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        /// <param name="arg1">The arg1.</param>
        /// <param name="arg2">The arg2.</param>
        public void ErrorFormat( string format, object arg0, object arg1, object arg2 )
        {
            _logs[ Level.Error ].Add( string.Format( format, arg0, arg1, arg2 ) );
        }

        /// <summary>
        /// Errors the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        /// <param name="arg1">The arg1.</param>
        public void ErrorFormat( string format, object arg0, object arg1 )
        {
            _logs[ Level.Error ].Add( string.Format( format, arg0, arg1 ) );
        }

        /// <summary>
        /// Errors the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        public void ErrorFormat( string format, object arg0 )
        {
            _logs[ Level.Error ].Add( string.Format( format, arg0 ) );
        }

        /// <summary>
        /// Errors the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="args">The args.</param>
        public void ErrorFormat( string format, params object[] args )
        {
            _logs[ Level.Error ].Add( string.Format( format, args ) );
        }

        /// <summary>
        /// Fatals the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="exception">The exception.</param>
        public void Fatal( object message, Exception exception )
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendLine( message as string );
            builder.AppendLine( ExceptionLib.FormatException( exception ) );

            _logs[ Level.Fatal ].Add( builder.ToString() );
        }

        /// <summary>
        /// Fatals the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Fatal( object message )
        {
            _logs[ Level.Fatal ].Add( message as string );
        }

        /// <summary>
        /// Fatals the format.
        /// </summary>
        /// <param name="provider">The provider.</param>
        /// <param name="format">The format.</param>
        /// <param name="args">The args.</param>
        public void FatalFormat( IFormatProvider provider, string format, params object[] args )
        {
            _logs[ Level.Fatal ].Add( string.Format( format, args ) );
        }

        /// <summary>
        /// Fatals the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        /// <param name="arg1">The arg1.</param>
        /// <param name="arg2">The arg2.</param>
        public void FatalFormat( string format, object arg0, object arg1, object arg2 )
        {
            _logs[ Level.Fatal ].Add( string.Format( format, arg0, arg1, arg2 ) );
        }

        /// <summary>
        /// Fatals the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        /// <param name="arg1">The arg1.</param>
        public void FatalFormat( string format, object arg0, object arg1 )
        {
            _logs[ Level.Fatal ].Add( string.Format( format, arg0, arg1 ) );
        }

        /// <summary>
        /// Fatals the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        public void FatalFormat( string format, object arg0 )
        {
            _logs[ Level.Fatal ].Add( string.Format( format, arg0 ) );
        }

        /// <summary>
        /// Fatals the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="args">The args.</param>
        public void FatalFormat( string format, params object[] args )
        {
            _logs[ Level.Fatal ].Add( string.Format( format, args ) );
        }

        /// <summary>
        /// Infoes the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="exception">The exception.</param>
        public void Info( object message, Exception exception )
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendLine( message as string );
            builder.AppendLine( ExceptionLib.FormatException( exception ) );

            _logs[ Level.Info ].Add( builder.ToString() );
        }

        /// <summary>
        /// Infoes the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Info( object message )
        {
            _logs[ Level.Info ].Add( message as string );
        }

        /// <summary>
        /// Infoes the format.
        /// </summary>
        /// <param name="provider">The provider.</param>
        /// <param name="format">The format.</param>
        /// <param name="args">The args.</param>
        public void InfoFormat( IFormatProvider provider, string format, params object[] args )
        {
            _logs[ Level.Info ].Add( string.Format( format, args ) );
        }

        /// <summary>
        /// Infoes the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        /// <param name="arg1">The arg1.</param>
        /// <param name="arg2">The arg2.</param>
        public void InfoFormat( string format, object arg0, object arg1, object arg2 )
        {
            _logs[ Level.Info ].Add( string.Format( format, arg0, arg1, arg2 ) );
        }

        /// <summary>
        /// Infoes the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        /// <param name="arg1">The arg1.</param>
        public void InfoFormat( string format, object arg0, object arg1 )
        {
            _logs[ Level.Info ].Add( string.Format( format, arg0, arg1 ) );
        }

        /// <summary>
        /// Infoes the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        public void InfoFormat( string format, object arg0 )
        {
            _logs[ Level.Info ].Add( string.Format( format, arg0 ) );
        }

        /// <summary>
        /// Infoes the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="args">The args.</param>
        public void InfoFormat( string format, params object[] args )
        {
            _logs[ Level.Info ].Add( string.Format( format, args ) );
        }

        /// <summary>
        /// Gets a value indicating whether this instance is debug enabled.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is debug enabled; otherwise, <c>false</c>.
        /// </value>
        public bool IsDebugEnabled
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is error enabled.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is error enabled; otherwise, <c>false</c>.
        /// </value>
        public bool IsErrorEnabled
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is fatal enabled.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is fatal enabled; otherwise, <c>false</c>.
        /// </value>
        public bool IsFatalEnabled
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is info enabled.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is info enabled; otherwise, <c>false</c>.
        /// </value>
        public bool IsInfoEnabled
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is warn enabled.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is warn enabled; otherwise, <c>false</c>.
        /// </value>
        public bool IsWarnEnabled
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Warns the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="exception">The exception.</param>
        public void Warn( object message, Exception exception )
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendLine( message as string );
            builder.AppendLine( ExceptionLib.FormatException( exception ) );

            _logs[ Level.Warn ].Add( builder.ToString() );
        }

        /// <summary>
        /// Warns the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Warn( object message )
        {
            _logs[ Level.Warn ].Add( message as string );
        }

        /// <summary>
        /// Warns the format.
        /// </summary>
        /// <param name="provider">The provider.</param>
        /// <param name="format">The format.</param>
        /// <param name="args">The args.</param>
        public void WarnFormat( IFormatProvider provider, string format, params object[] args )
        {
            _logs[ Level.Warn ].Add( string.Format( format, args ) );
        }

        /// <summary>
        /// Warns the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        /// <param name="arg1">The arg1.</param>
        /// <param name="arg2">The arg2.</param>
        public void WarnFormat( string format, object arg0, object arg1, object arg2 )
        {
            _logs[ Level.Warn ].Add( string.Format( format, arg0, arg1, arg2 ) );
        }

        /// <summary>
        /// Warns the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        /// <param name="arg1">The arg1.</param>
        public void WarnFormat( string format, object arg0, object arg1 )
        {
            _logs[ Level.Warn ].Add( string.Format( format, arg0, arg1 ) );
        }

        /// <summary>
        /// Warns the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="arg0">The arg0.</param>
        public void WarnFormat( string format, object arg0 )
        {
            _logs[ Level.Warn ].Add( string.Format( format, arg0 ) );
        }

        /// <summary>
        /// Warns the format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="args">The args.</param>
        public void WarnFormat( string format, params object[] args )
        {
            _logs[ Level.Warn ].Add( string.Format( format, args ) );
        }

        #endregion

        #region ILoggerWrapper Members

        /// <summary>
        /// Gets the logger.
        /// </summary>
        /// <value>The logger.</value>
        public ILogger Logger
        {
            get
            {
                return null;
            }
        }

        #endregion

        /// <summary>
        /// Resets this instance.
        /// </summary>
        public void Reset()
        {
            foreach ( Level level in _logs.Keys )
            {
                _logs[ level ].Clear();
            }

            _logs.Clear();

            _logs.Add( Level.Emergency, new List<string>() );
            _logs.Add( Level.Fatal, new List<string>() );
            _logs.Add( Level.Alert, new List<string>() );
            _logs.Add( Level.Critical, new List<string>() );
            _logs.Add( Level.Severe, new List<string>() );
            _logs.Add( Level.Error, new List<string>() );
            _logs.Add( Level.Warn, new List<string>() );
            _logs.Add( Level.Notice, new List<string>() );
            _logs.Add( Level.Info, new List<string>() );
            _logs.Add( Level.Debug, new List<string>() );
            _logs.Add( Level.Trace, new List<string>() );
            _logs.Add( Level.Verbose, new List<string>() );
            _logs.Add( ExtendedLogImplementation.Statistics, new List<string>() );
            _logs.Add( Level.All, new List<string>() );
        }

        /// <summary>
        /// Gets the messages for log.
        /// </summary>
        /// <param name="level">The level.</param>
        /// <returns></returns>
        public IEnumerable<string> GetMessagesForLog( Level level )
        {
            return _logs[ level ].ToArray();
        }

    }
}
